home *** CD-ROM | disk | FTP | other *** search
/ Ray Dream Studio 5 / Ray Dream.iso / pc / DreamSDK / Windows / SAMPLES / EXPORTER / DXF / COMDXF.CPP next >
Encoding:
C/C++ Source or Header  |  1997-07-11  |  11.5 KB  |  443 lines

  1. /* $Id: COMDXF.cpp 1.9 1997/05/12 19:04:17 damien Exp $ */
  2.  
  3. // Copyright (c) 1990-1995 Ray Dream, Inc. All rights reserved.
  4.  
  5. #include "math.h"
  6.  
  7. #ifndef __COMDXF__
  8. #include "COMDXF.h"
  9. #endif
  10.  
  11. #ifndef __RGBHSV__
  12. #include "rgbhsv.h"
  13. #endif
  14.  
  15. #ifndef __3DCOFAIL__
  16. #include "3DCoFail.h"
  17. #endif
  18.  
  19. #ifndef __I3DSHUTI__
  20. #include "I3DShUti.h"
  21. #endif
  22.  
  23. #ifndef __I3DSHTRE__
  24. #include "I3DShTre.h"
  25. #endif
  26.  
  27. #ifndef __I3DSHOBJ__
  28. #include "I3DShObj.h"
  29. #endif
  30.  
  31. #ifndef __I3DSHSCN__
  32. #include "I3DShScn.h"
  33. #endif
  34.  
  35. #ifndef __DXFDLL__
  36. #include "DXFDll.h"
  37. #endif
  38.  
  39. #define kManyFacetsError    0x2BC
  40. #define kStandardFacetsError    0x1000
  41. #define kFewfacetsError    0x2000
  42.  
  43. void Transform(VECTOR3D &res, const MATRIX3D& AA, const VECTOR3D& VV) {
  44.     NUM3D    xx,yy,zz;
  45.     xx=VV[0];
  46.     yy=VV[1];
  47.     zz=VV[2];
  48.     res[0]=AA.fix*xx+AA.fjx*yy+AA.fkx*zz;
  49.     res[1]=AA.fiy*xx+AA.fjy*yy+AA.fky*zz;
  50.     res[2]=AA.fiz*xx+AA.fjz*yy+AA.fkz*zz;
  51.     }
  52.  
  53. void TransformPoint(VECTOR3D &res, const TREETRANSFORM3D &AA,const VECTOR3D& VV) {
  54.     Transform(res, AA.fR, VV);
  55.     res[0]=res[0]*AA.fS;
  56.     res[1]=res[1]*AA.fS;
  57.     res[2]=res[2]*AA.fS;
  58.  
  59.     res[0]+=AA.fT[0];
  60.     res[1]+=AA.fT[1];
  61.     res[2]+=AA.fT[2];
  62.     }
  63.  
  64. unsigned short QuickFixColorToUShort(NUM3D col)    {
  65.     double db;
  66.  
  67.     if (col>1.0)    col = 1.0;
  68.     db=(double)col;
  69.     db *= 65535;
  70.     return (unsigned short) db;
  71.     }
  72.  
  73. short ConvertToDXFColor(const COLOR3D& col) {
  74.     unsigned short dxfColor;
  75.     RDRGBColor rgb;
  76.     RDHSVColor hsv;
  77.     
  78.     rgb.rr = QuickFixColorToUShort(col.R);
  79.     rgb.gg = QuickFixColorToUShort(col.G);
  80.     rgb.bb = QuickFixColorToUShort(col.B);
  81.     RDRGB2HSV(rgb, hsv);
  82.   unsigned short sextant = hsv.hue / 10922; 
  83.   if ((((double(hsv.hue)/ 10922) - sextant) < 0.1) && (hsv.saturation > 60000))  //standard colors
  84.       dxfColor = sextant + 1;
  85.   else if (hsv.saturation <3000) { //grays 
  86.       short grayBrightness = (short)((long)(4680L + (long)hsv.value ) / 9362);  
  87.       switch (grayBrightness) {   
  88.           case 0: //black
  89.               dxfColor = 0;
  90.               break;
  91.           case 7: //white 
  92.               dxfColor = 7;
  93.               break;
  94.           default://real grays 
  95.               dxfColor = 249 + grayBrightness;
  96.           }
  97.       }
  98.   else { 
  99.         dxfColor = 10 +
  100.                              hsv.hue/273  +
  101.                              2*(unsigned short)(((unsigned short)65535-hsv.value)/13107);
  102.         if (hsv.saturation<32767) dxfColor++;
  103.         dxfColor = ((dxfColor>255)?255:dxfColor); 
  104.         }                                             // but here it should not go further than 249
  105.     return (short) dxfColor;
  106.     }
  107.     
  108. //########################################################################################
  109. struct DXFWriteFacetStruct {
  110.     I3DShPrimitive* primitive;
  111.     IShFileStream* stream;
  112.     TREETRANSFORM3D* transform;
  113.     char* name;
  114.     ULONG count;
  115.     short color;
  116.     };
  117.     
  118. void ConvertQuickFixToDouble(const NUM3D num, double &dbl) {
  119.     dbl=(double)num*4.0;     //eml : scaling factor (1 DXF unit= 1 inch)
  120.     }
  121.  
  122. void WriteVertex(IShFileStream* stream, VECTOR3D vertex, short id) {
  123.     double db;
  124.  
  125.     stream->PutLong(1);
  126.     stream->PutLong(id);
  127.     stream->PutEOL();
  128.     ConvertQuickFixToDouble(vertex[0], db);
  129.     stream->PutDouble(db);
  130.     stream->PutEOL();
  131.  
  132.     stream->PutLong(2);
  133.     stream->PutLong(id);
  134.     stream->PutEOL();
  135.     ConvertQuickFixToDouble(vertex[1], db);
  136.     stream->PutDouble(db);
  137.     stream->PutEOL();
  138.  
  139.     stream->PutLong(3);
  140.     stream->PutLong(id);
  141.     stream->PutEOL();
  142.     ConvertQuickFixToDouble(vertex[2], db);
  143.     stream->PutDouble(db);
  144.     stream->PutEOL();
  145.     }
  146.  
  147. Boolean IsFacetDirect(FACET3D* facet)    {
  148.     VECTOR3D        NN;
  149.     VECTOR3D        AB;
  150.     VECTOR3D        AC;
  151.     NUM3D norm;
  152.     NUM3D vectProd;
  153.     
  154.     for (int i=0; i<3; i++) {
  155.         NN[i] = facet->fVertices[0].fNormal[i] + facet->fVertices[1].fNormal[i] + facet->fVertices[2].fNormal[i];
  156.         AB[i] = facet->fVertices[1].fVertex[i] - facet->fVertices[0].fVertex[i];
  157.         AC[i] = facet->fVertices[2].fVertex[i] - facet->fVertices[0].fVertex[i];
  158.         }
  159.     norm=sqrt(SQR(AB[0]) + SQR(AB[1]) + SQR(AB[2]));
  160.     AB[0]/=norm;
  161.     AB[1]/=norm;
  162.     AB[2]/=norm;
  163.     //AB./*Pseudo*/Normalize();
  164.     norm=sqrt(SQR(AC[0]) + SQR(AC[1]) + SQR(AC[2]));
  165.     AC[0]/=norm;
  166.     AC[1]/=norm;
  167.     AC[2]/=norm;
  168.     //AC./*Pseudo*/Normalize();
  169.     
  170.     vectProd =(AB[1]*AC[2] - AB[2]*AC[1]) * NN[0];
  171.     vectProd+=(AB[2]*AC[0] - AB[0]*AC[2]) * NN[1];
  172.     vectProd+=(AB[0]*AC[1] - AB[1]*AC[0]) * NN[2];
  173.     return (vectProd >= 0.0);
  174.     }    // end 3.0.3
  175.  
  176. void WriteFacets(FACET3D* facet, void* privData) {
  177.     VECTOR3D vertex;
  178.     DXFWriteFacetStruct* data = (DXFWriteFacetStruct*)privData;
  179.     IShFileStream* stream = data->stream;
  180.     
  181.     stream->PutLine("0");
  182.     stream->PutLine("3DFACE");
  183.     
  184.     // The name and color HAS to be put in each 3dFace!!
  185.     stream->PutLine("8");
  186.     stream->PutString(data->name);
  187.     stream->PutLong(data->count);     // To make sure the name is different for each instance of the same object
  188.     stream->PutEOL();
  189.  
  190.     stream->PutLine("62");
  191.     stream->PutLong(data->color);
  192.     stream->PutEOL();
  193.     
  194.     //-- 3.0.3 YC: output the vertices in the direct trigonometric order
  195.     if (IsFacetDirect(facet))    {
  196.         for (short v=0; v<=2; v++) {
  197.             TransformPoint(vertex, *data->transform, facet->fVertices[v].fVertex);
  198.             WriteVertex(stream, vertex, v);
  199.             }
  200.         }
  201.     else    {        // 3.0.3 YC (cont.)
  202.         TransformPoint(vertex, *data->transform, facet->fVertices[0].fVertex);
  203.         WriteVertex(stream, vertex, 0);
  204.         TransformPoint(vertex, *data->transform, facet->fVertices[2].fVertex);
  205.         WriteVertex(stream, vertex, 2);
  206.         TransformPoint(vertex, *data->transform, facet->fVertices[1].fVertex);
  207.         WriteVertex(stream, vertex, 1);
  208.         }        // 3.0.3 YC end.
  209.     // Fourth point equal to third
  210.     WriteVertex(stream, vertex, 3);
  211.     }
  212.     
  213. void WriteInstance(IShFileStream* stream, I3DShInstance* anInstance, ULONG count) {
  214.     TREETRANSFORM3D transform;
  215.     char name[255] = "Obj";
  216.     COLOR3D col1, col2;
  217.     short dxfColor;
  218.     I3DShTreeElement*    tree;
  219.     I3DShObject*             object;
  220.     I3DShPrimitive*        primitive;
  221.     DXFWriteFacetStruct ws;
  222.     IUnknown*                    lightOrCameraInstance = NULL;
  223.  
  224.     // Make sure this is not a light or camera instance
  225.     anInstance->QueryInterface(IID_I3DShCamera, (LPVOID*) &lightOrCameraInstance);
  226.     if (!lightOrCameraInstance)
  227.         anInstance->QueryInterface(IID_I3DShLightsource, (LPVOID*) &lightOrCameraInstance);
  228.     if (lightOrCameraInstance)    {
  229.         lightOrCameraInstance->Release();
  230.         return;
  231.         }
  232.  
  233.     object = anInstance->Get3DObject();
  234.     object->QueryInterface(IID_I3DShPrimitive, (LPVOID*) &primitive);
  235.     if (primitive)    {
  236.         anInstance->QueryInterface(IID_I3DShTreeElement, (LPVOID*) &tree);
  237.         // Calc Name
  238.         tree->GetName(name);
  239.         char* p;
  240.         int i;
  241.         for (p=name, i=0; i<12 && *p!=0; i++, p++) {    // Make the name AutoCAD-friendly
  242.             if (((*p<'a') || (*p>'z')) &&
  243.                     ((*p<'A') || (*p>'Z')) &&
  244.                     ((*p<'0') || (*p>'9'))) {
  245.                 *p = '_';
  246.                 }
  247.             }
  248.         *p = '\0';
  249.  
  250.         // Calc color
  251.         anInstance->GetMainColors(&col1, &col2);
  252.         dxfColor = ConvertToDXFColor(col1);
  253.     
  254.         // Fill data structure for call back
  255.         ws.primitive = primitive;
  256.         ws.stream = stream;
  257.         tree->GetGlobalTransform(&transform);
  258.         ws.transform = &transform;
  259.         ws.name = name;
  260.         ws.count = count;
  261.         ws.color = dxfColor;
  262.         /*if (primitive->IsPatchBased())    {
  263.             primitive->EnumPatches(WritePatches, &ws);
  264.             }
  265.         else    {
  266.             primitive->EnumFacets(WriteFacets, &ws);
  267.             }*/
  268.         anInstance->EnumFacetsWithConversion(WriteFacets, &ws, TRUE, kStandardFacetsError);
  269.         tree->Release();
  270.         primitive->Release();
  271.         }
  272.  
  273.     gShellUtilities->ProgressIncrement(1);
  274.     }
  275.  
  276. //########################################################################################
  277. void WriteDXFBegin(IShFileStream* stream) {
  278.     stream->PutLine("0");
  279.     stream->PutLine("SECTION");
  280.     stream->PutLine("2");
  281.     stream->PutLine("HEADER");
  282.     stream->PutLine("0");
  283.     stream->PutLine("ENDSEC");
  284.  
  285.     stream->PutLine("999");
  286.     stream->PutLine("Created using Ray Dream Designer(R) 3");
  287.  
  288.     stream->PutLine("0");
  289.     stream->PutLine("SECTION");
  290.     stream->PutLine("2");
  291.     stream->PutLine("ENTITIES");
  292.     }
  293.     
  294. void WriteDXFEnd(IShFileStream* stream) {
  295.     stream->PutLine("0");
  296.     stream->PutLine("ENDSEC");
  297.     stream->PutLine("0");
  298.     stream->PutLine("EOF");
  299.     }
  300.     
  301. //########################################################################################
  302.  
  303. TDXFExporter::TDXFExporter()    {
  304.   fCRef=0; // Reference Counter
  305.   global_count_Obj++; 
  306.     }
  307.  
  308. TDXFExporter::~TDXFExporter() {
  309.   global_count_Obj--; 
  310.   }
  311.   
  312. // IUnknown Interface :
  313. HRESULT TDXFExporter::QueryInterface(REFIID riid,LPVOID* ppvObj) {
  314.   *ppvObj=NULL;
  315.   
  316.   // The TDXFExporter knows the interfaces of the parent Objects
  317.   if (IsEqualIID(riid, IID_IUnknown))
  318.     *ppvObj=(LPVOID)this;
  319.   else if (IsEqualIID(riid, IID_I3DExExportFilter))
  320.     *ppvObj=(LPVOID)this;
  321.   else if (IsEqualIID(riid, IID_I3DExDataExchanger))
  322.     *ppvObj=(LPVOID)this;
  323.   else if (IsEqualIID(riid, IID_I3DExtension))
  324.     *ppvObj=(LPVOID)this;
  325.     
  326.   // we must add reference if we return an interface
  327.   if (*ppvObj!=NULL) {
  328.     ((LPUNKNOWN)*ppvObj)->AddRef();
  329.     return NOERROR;
  330.     }
  331.   else {
  332.     return ResultFromScode(E_NOINTERFACE);
  333.     }
  334.   }
  335.  
  336. ULONG TDXFExporter::AddRef() {
  337.   return fCRef++;
  338.   }
  339.   
  340. ULONG TDXFExporter::Release() {
  341.   ULONG UnreleaseObject=fCRef--;
  342.   
  343.   if (fCRef==0)
  344.      delete this; // No reference left, so destroy the object
  345.   
  346.   return UnreleaseObject;
  347.   }
  348.  
  349. // I3DExtension methods :
  350. I3DExtension* TDXFExporter::Clone() {
  351.   TDXFExporter* theClone = new TDXFExporter;
  352.   if (theClone) {
  353.     theClone->AddRef();
  354.     }                               
  355.   return theClone;
  356.   }   
  357.  
  358. HRESULT TDXFExporter::ShellUtilitiesInit(IShUtilities* shellUtilities) {
  359.     InitCoFailure(shellUtilities);
  360.   return NOERROR;
  361.   }
  362.  
  363. // I3DExDataExchanger methods :
  364. ExtensionDataMap* TDXFExporter::GetExtensionDataMap() {
  365.   return NULL;
  366.   }
  367.  
  368. void* TDXFExporter::GetExtensionDataBuffer() {
  369.   return NULL; // no data
  370.   }
  371.   
  372. HRESULT TDXFExporter::ExtensionDataChanged() {
  373.   return NOERROR;
  374.   }
  375.  
  376. HRESULT TDXFExporter::HandleEvent(ULONG SourceID) {
  377.   return ResultFromScode(E_NOTIMPL);
  378.   }
  379.  
  380. short TDXFExporter::GetResID() {
  381.   return 128; // this is the view ID in the resource file.
  382.   }
  383.   
  384. BOOLEAN TDXFExporter::Prepare(I3DShScene* /*scene*/, I3DShTreeElement* /*fatherTree*/)    {
  385.     return TRUE;
  386.     }
  387.  
  388. BOOLEAN TDXFExporter::WantsOptionDialog()    {
  389.     return FALSE;    // no UI
  390.     }
  391.  
  392. HRESULT TDXFExporter::NeededDiskSpace(char* /*fullPathName*/, I3DShScene* /*scene*/, I3DShTreeElement* /*fatherTree*/, ULONG* /*diskSpace*/)    {
  393.     return NOERROR;     // We cannot tell, so we do not do anything...
  394.     }
  395.  
  396. HRESULT TDXFExporter::DoExport(char* fullPathName, I3DShScene* scene, I3DShTreeElement* /*fatherTree*/)    {
  397.     DECLAREVOLATILE(IShFileStream*, stream = NULL);
  398.     ULONG nbInst = 0;
  399.     FailInfo    fi;
  400.  
  401.     if (TRY(fi))    {
  402.         nbInst =scene->GetInstancesCount();
  403.         
  404.         gShellUtilities->ProgressStart("Exporting DXF", nbInst);
  405.         
  406.         gShellUtilities->CoCreateInstance(CLSID_StandardFileStream, NULL, CLSCTX_INPROC_SERVER, IID_IShFileStream, (LPVOID*) &stream);
  407.         FailNIL(stream);
  408.         FailOSErr((short)stream->InitFileStream(fullPathName, kShStreamOut));
  409.         stream->SetMacOSInfo(IDTYPE('t','t','x','t'), IDTYPE('T','E','X','T'));         // Needed on the Mac, Will not do anything on the PC
  410.         
  411.         WriteDXFBegin(stream);
  412.  
  413.         for (ULONG i=1; i<=nbInst; ++i)    {
  414.             WriteInstance(stream, scene->GetInstanceByIndex(i), i);
  415.             } 
  416.  
  417.         WriteDXFEnd(stream);
  418.  
  419.         stream->Release();
  420.         gShellUtilities->ProgressDone();
  421.         fi.Success();
  422.         }
  423.     else    {
  424.         stream->Release();
  425.         gShellUtilities->ProgressDone();
  426.         fi.ReSignal();
  427.         }
  428.     return NOERROR;
  429.     }
  430.  
  431. BOOLEAN TDXFExporter::WantsPreview() {
  432.     return FALSE;
  433.     }
  434.  
  435. HRESULT TDXFExporter::GetPreviewSize(short* /*sizeh*/, short* /*sizev*/)    {
  436.     return ResultFromScode(E_NOTIMPL);
  437.     }
  438.  
  439. HRESULT TDXFExporter::SetPreview(IShRasterOffscreen* /*preview*/)    {
  440.     return ResultFromScode(E_NOTIMPL);
  441.     }
  442.  
  443.